package com.youlai.quarkus.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.quarkus.system.common.constant.SecurityConstants;
import com.youlai.quarkus.system.common.constant.SystemConstants;
import com.youlai.quarkus.system.common.redis.IRedisService;
import com.youlai.quarkus.system.common.util.SecurityIdentityContext;
import com.youlai.quarkus.system.converter.UserConverter;
import com.youlai.quarkus.system.mapper.SysMenuMapper;
import com.youlai.quarkus.system.mapper.SysRoleMapper;
import com.youlai.quarkus.system.mapper.SysUserMapper;
import com.youlai.quarkus.system.model.bo.UserBO;
import com.youlai.quarkus.system.model.dto.UserAuthInfo;
import com.youlai.quarkus.system.model.entity.SysUser;
import com.youlai.quarkus.system.model.form.UserForm;
import com.youlai.quarkus.system.model.query.UserPageQuery;
import com.youlai.quarkus.system.model.vo.UserExportVO;
import com.youlai.quarkus.system.model.vo.UserInfoVO;
import com.youlai.quarkus.system.model.vo.UserPageVO;
import com.youlai.quarkus.system.service.SysUserService;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户业务实现类
 *
 * @author haoxr
 * @since 2022/1/14
 */

@ApplicationScoped
@RequiredArgsConstructor
public class SysUserServiceImpl implements SysUserService {

    private final SysUserMapper baseMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysMenuMapper sysMenuMapper;
    private final UserConverter userConverter;
    private final IRedisService redisService;
    private final SecurityIdentityContext identityContext;

    @Override
    public IPage<UserPageVO> getUserPage(UserPageQuery queryParams) {
        // 参数构建
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<UserBO> page = new Page<>(pageNum, pageSize);
        // 查询数据
        Page<UserBO> userBoPage = this.baseMapper.getUserPage(page, queryParams);
        // 实体转换
        Page<UserPageVO> userVoPage = userConverter.bo2Vo(userBoPage);
        return userVoPage;
    }

    @Override
    public SysUser getUser(Integer userId) {
        return this.baseMapper.getUser(userId);
    }

    @Override
    public UserForm getUserFormData(Long userId) {
        return null;
    }

    @Override
    public boolean saveUser(UserForm userForm) {
        String username = userForm.getUsername();
        long count = baseMapper.selectCount(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        Assert.isTrue(count == 0, "用户名已存在");
        // 实体转换 form->entity
        SysUser entity = userConverter.form2Entity(userForm);

        // 设置默认加密密码
//        String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
        String defaultEncryptPwd = BCrypt.hashpw(SystemConstants.DEFAULT_PASSWORD);
        entity.setPassword(defaultEncryptPwd);
        // 新增用户
        baseMapper.insert(entity);
        // 保存用户角色
//        userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        return true;
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public boolean updateUser(Long userId, UserForm userForm) {
        String username = userForm.getUsername();

        long count = baseMapper.selectCount(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .ne(SysUser::getId, userId)
        );
        Assert.isTrue(count == 0, "用户名已存在");

        // form -> entity
        SysUser entity = userConverter.form2Entity(userForm);

        // 修改用户
        boolean result = baseMapper.updateById(entity) > 0;
        if (result) {
            // 保存用户角色
//            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    @Override
    public boolean deleteUsers(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.asList(idsStr.split(",")).stream()
                .map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
        boolean result = baseMapper.deleteByIds(ids) > 0;
        return result;
    }

    @Override
    public boolean updatePassword(Long userId, String password) {
        return baseMapper.update(new LambdaUpdateWrapper<SysUser>()
                .eq(SysUser::getId, userId)
                .set(SysUser::getPassword, BCrypt.hashpw(password))
        ) > 0;
    }

    @Override
    public UserAuthInfo getUserAuthInfo(String username) {
        UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
        if (userAuthInfo != null) {
            Set<String> roles = userAuthInfo.getRoles();
            if (CollectionUtil.isNotEmpty(roles)) {
                Set<String> perms = sysMenuMapper.listRolePerms(roles);
                userAuthInfo.setPerms(perms);
            }

            // 获取最大范围的数据权限
            Integer dataScope = sysRoleMapper.getMaximumDataScope(roles);
            userAuthInfo.setDataScope(dataScope);
        }
        return userAuthInfo;
    }

    @Override
    public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
        List<UserExportVO> list = this.baseMapper.listExportUsers(queryParams);
        return list;
    }

    @Override
    public UserInfoVO getCurrentUserInfo() {
        String username = identityContext.getUser().getUsername();
        // 获取登录用户基础信息
        SysUser user = baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username)
                .select(
                        SysUser::getId,
                        SysUser::getUsername,
                        SysUser::getNickname,
                        SysUser::getAvatar
                )
        );
        // entity->VO
        UserInfoVO userInfoVO = userConverter.toUserInfoVo(user);

        // 用户角色集合
        Set<String> roles = identityContext.getRoles();
        userInfoVO.setRoles(roles);

        // 用户权限集合
        Set<String> perms = redisService.get(SecurityConstants.USER_PERMS_CACHE_PREFIX + user.getId(), Set.class);
        userInfoVO.setPerms(perms);

        return userInfoVO;
    }

    @Override
    public boolean updateUserStatus(Long userId, Integer status) {
        baseMapper.update(new LambdaUpdateWrapper<SysUser>()
                .eq(SysUser::getId, userId)
                .set(SysUser::getStatus, status)
        );
        return true;
    }
}
